From e83a8e7c2bd64d7f9ec296844e28f3c338645f95 Mon Sep 17 00:00:00 2001 From: "cl349@firebug.cl.cam.ac.uk" Date: Mon, 19 Sep 2005 14:47:56 +0000 Subject: [PATCH] Fire watches once immediately upon registration. It matches the model of programming used to avoid races with watches, and also makes re-establishing watches on daemon restart easier. Signed-off-by: Rusty Russell Signed-off-by: Christian Limpach --- .../drivers/xen/blkback/xenbus.c | 3 +-- .../drivers/xen/blktap/xenbus.c | 3 +-- .../drivers/xen/netback/xenbus.c | 3 +-- .../drivers/xen/netfront/netfront.c | 4 ---- .../drivers/xen/tpmback/xenbus.c | 3 +-- .../drivers/xen/tpmfront/tpmfront.c | 1 - tools/xenstore/testsuite/07watch.test | 4 +++- tools/xenstore/testsuite/14complexperms.test | 5 +++-- tools/xenstore/xenstored_watch.c | 3 +++ tools/xenstore/xs_test.c | 17 +++++++++++++++-- 10 files changed, 28 insertions(+), 18 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c index c081aa8240..e884a1a213 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c @@ -228,6 +228,7 @@ static int blkback_probe(struct xenbus_device *dev, be->dev = dev; be->backend_watch.node = dev->nodename; be->backend_watch.callback = backend_changed; + /* Will implicitly call backend_changed once. */ err = register_xenbus_watch(&be->backend_watch); if (err) { be->backend_watch.node = NULL; @@ -249,8 +250,6 @@ static int blkback_probe(struct xenbus_device *dev, } dev->data = be; - - backend_changed(&be->backend_watch, dev->nodename); return 0; free_be: diff --git a/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c index 06d07cacf1..771ff28eaa 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c +++ b/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c @@ -172,6 +172,7 @@ static int blkback_probe(struct xenbus_device *dev, be->dev = dev; be->backend_watch.node = dev->nodename; be->backend_watch.callback = backend_changed; + /* Registration implicitly fires backend_changed once */ err = register_xenbus_watch(&be->backend_watch); if (err) { be->backend_watch.node = NULL; @@ -193,8 +194,6 @@ static int blkback_probe(struct xenbus_device *dev, } dev->data = be; - - backend_changed(&be->backend_watch, dev->nodename); return 0; free_be: diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c index d5a41728f7..1e1d27ecaa 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c +++ b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c @@ -242,6 +242,7 @@ static int netback_probe(struct xenbus_device *dev, be->dev = dev; be->backend_watch.node = dev->nodename; be->backend_watch.callback = backend_changed; + /* Registration implicitly calls backend_changed. */ err = register_xenbus_watch(&be->backend_watch); if (err) { be->backend_watch.node = NULL; @@ -263,8 +264,6 @@ static int netback_probe(struct xenbus_device *dev, } dev->data = be; - - backend_changed(&be->backend_watch, dev->nodename); return 0; free_be: diff --git a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c index bc6fa05f01..7f7d990ef2 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c @@ -1284,10 +1284,6 @@ static int netfront_probe(struct xenbus_device *dev, return err; } - - /* Call once in case entries already there. */ - watch_for_status(&info->watch, info->watch.node); - return 0; } diff --git a/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c index 4e2a11f838..59237b511b 100644 --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c @@ -213,6 +213,7 @@ static int tpmback_probe(struct xenbus_device *dev, be->dev = dev; be->backend_watch.node = dev->nodename; + /* Implicitly calls backend_changed() once. */ be->backend_watch.callback = backend_changed; be->instance = -1; err = register_xenbus_watch(&be->backend_watch); @@ -236,8 +237,6 @@ static int tpmback_probe(struct xenbus_device *dev, } dev->data = be; - - backend_changed(&be->backend_watch, dev->nodename); return err; free_be: diff --git a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c index 9df476781f..ae94b3bbef 100644 --- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c @@ -411,7 +411,6 @@ static int tpmfront_probe(struct xenbus_device *dev, return err; } - watch_for_status(&info->watch, info->watch.node); return 0; } diff --git a/tools/xenstore/testsuite/07watch.test b/tools/xenstore/testsuite/07watch.test index 5ce41aa80b..5ae025765e 100644 --- a/tools/xenstore/testsuite/07watch.test +++ b/tools/xenstore/testsuite/07watch.test @@ -168,10 +168,12 @@ expect 1: waitwatch failed: Connection timed out # Watch event must have happened before we registered interest. 1 watch / token 2 write /test/subnode contents2 -1 watch / token2 0 +1 watchnoack / token2 0 expect 1:/test/subnode:token 1 waitwatch 1 ackwatch token +expect 1:/:token2 +1 waitwatch expect 1: waitwatch failed: Connection timed out 1 waitwatch 1 close diff --git a/tools/xenstore/testsuite/14complexperms.test b/tools/xenstore/testsuite/14complexperms.test index dc4b0cdbb6..9ac47a70b8 100644 --- a/tools/xenstore/testsuite/14complexperms.test +++ b/tools/xenstore/testsuite/14complexperms.test @@ -23,7 +23,8 @@ expect *Permission denied getperm /dir/file expect *Permission denied setperm /dir/file 0 NONE -watch /dir/file token +# We get no watch event when there's no permission. It's a corner case. +watchnoack /dir/file token 1 write /dir/file contents 1 rm /dir/file expect waitwatch failed: Connection timed out @@ -63,7 +64,7 @@ expect *Permission denied getperm /dir/file expect *Permission denied setperm /dir/file 0 NONE -watch /dir/file token +watchnoack /dir/file token 1 write /dir/file contents 1 rm /dir/file expect waitwatch failed: Connection timed out diff --git a/tools/xenstore/xenstored_watch.c b/tools/xenstore/xenstored_watch.c index a543f8a495..74dd773694 100644 --- a/tools/xenstore/xenstored_watch.c +++ b/tools/xenstore/xenstored_watch.c @@ -236,6 +236,9 @@ void do_watch(struct connection *conn, struct buffered_data *in) trace_create(watch, "watch"); talloc_set_destructor(watch, destroy_watch); send_ack(conn, XS_WATCH); + + /* We fire once up front: simplifies clients and restart. */ + add_event(conn, watch, watch->node); } void do_watch_ack(struct connection *conn, const char *token) diff --git a/tools/xenstore/xs_test.c b/tools/xenstore/xs_test.c index 3d90632e24..85d3d25dde 100644 --- a/tools/xenstore/xs_test.c +++ b/tools/xenstore/xs_test.c @@ -200,6 +200,7 @@ static void __attribute__((noreturn)) usage(void) " setperm ...\n" " shutdown\n" " watch \n" + " watchnoack \n" " waitwatch\n" " ackwatch \n" " unwatch \n" @@ -480,10 +481,20 @@ static void do_shutdown(unsigned int handle) failed(handle); } -static void do_watch(unsigned int handle, const char *node, const char *token) +static void do_watch(unsigned int handle, const char *node, const char *token, + bool swallow_event) { if (!xs_watch(handles[handle], node, token)) failed(handle); + + /* Convenient for testing... */ + if (swallow_event) { + char **vec = xs_read_watch(handles[handle]); + if (!vec || !streq(vec[0], node) || !streq(vec[1], token)) + failed(handle); + if (!xs_acknowledge_watch(handles[handle], token)) + failed(handle); + } } static void set_timeout(void) @@ -767,7 +778,9 @@ static void do_command(unsigned int default_handle, char *line) else if (streq(command, "shutdown")) do_shutdown(handle); else if (streq(command, "watch")) - do_watch(handle, arg(line, 1), arg(line, 2)); + do_watch(handle, arg(line, 1), arg(line, 2), true); + else if (streq(command, "watchnoack")) + do_watch(handle, arg(line, 1), arg(line, 2), false); else if (streq(command, "waitwatch")) do_waitwatch(handle); else if (streq(command, "ackwatch")) -- 2.30.2